package com.hengshan.service.impl;

import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson2.JSONObject;
import com.hengshan.common.ResultBody;
import com.hengshan.common.enums.RedisKey;
import com.hengshan.common.enums.ReturnCode;
import com.hengshan.common.utils.JWTUtil;
import com.hengshan.common.utils.RedisUtil;
import com.hengshan.common.utils.ServletUtils;
import com.hengshan.domain.event.LoginEvent;
import com.hengshan.domain.LoginBody;
import com.hengshan.domain.LoginUser;
import com.hengshan.exception.SystemException;
import lombok.RequiredArgsConstructor;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

@Service
@RequiredArgsConstructor
public class LoginService {

    private final AuthenticationManager authenticationManager;

    /**
     * 用户登录
     *
     * @param loginBody 用户登录信息
     */
    public JSONObject login(LoginBody loginBody) {
        String username = loginBody.getUsername();
        String password = loginBody.getPassword();

        // 校验验证码
        //String code = StringUtils.hasText(loginBody.getCode()) ? loginBody.getCode() : "";
        //String uuid = StringUtils.hasText(loginBody.getUuid()) ? loginBody.getUuid() : "";
        //String verifyKey = RedisKey.CAPTCHA_KEY + uuid;
        //String captcha = RedisUtil.get(verifyKey);
        //RedisUtil.del(verifyKey);
        //if (captcha == null || !code.equalsIgnoreCase(captcha)) {
        //    recordLoginInfo(username, "0", ReturnCode.CAPTCHA_EXPIRE.getMessage());
        //    throw new SystemException(ReturnCode.CAPTCHA_EXPIRE);
        //}

        //判断是否通过认证，spring security通过UserDetailsService做认证 默认是内存方式，需实现该类重写方法走数据库认证
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password);
        Authentication authentication = authenticationManager.authenticate(authenticationToken);

        //认证通过，生成token，返给前端同时保存登录用户信息到redis
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        loginUser.setLoginTime(System.currentTimeMillis());
        String userId = loginUser.getUser().getId().toString();
        String jwt = JWTUtil.createJWT(userId, null);
        RedisUtil.set(RedisKey.LOGIN_USER_KEY + userId, loginUser, 120);
        JSONObject json = new JSONObject();
        json.put("token", jwt);
        //发布登录事件
        recordLoginInfo(username, "0", ReturnCode.SUCCESS.getMessage());
        return json;
    }

    /**
     * 用户登出
     */
    public ResultBody logout() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        RedisUtil.del(RedisKey.LOGIN_USER_KEY + loginUser.getUser().getId());
        return ResultBody.success();
    }

    /**
     * 记录登录信息
     *
     * @param username 用户名
     * @param status   状态
     * @param message  消息内容
     */
    private void recordLoginInfo(String username, String status, String message) {
        LoginEvent loginEvent = new LoginEvent();
        loginEvent.setUsername(username);
        loginEvent.setStatus(status);
        loginEvent.setMessage(message);
        loginEvent.setRequest(ServletUtils.getRequest());
        SpringUtil.getApplicationContext().publishEvent(loginEvent);
    }
}
